--[[Block类
方块共享类
]]
Block = class()

function Block:init(id,tex,destoryTime)
    self.id = id
    self.tex = tex
    self.solidBlock = true --固体方块
    self.opacityBlock = false --透明方块
    self.destoryTime = destoryTime
    self.lightDelay = Brightness.Max    -- 方块透明度(亮度衰减值,整数)
    self.brightness = 0  -- 方块发光亮度(亮度值，整数，0~Brightness.Max)
    Block.blocks[id] = self
end

function Block:getTesselator(ts)
    return ts[1]
end

function Block:render(ts,x,y,z)
    local t = self:getTesselator(ts)
    if self:shouldRenderFace(x - 1,y,z) then
        self:renderFace(t,x,y,z,Left)
    end
    if self:shouldRenderFace(x + 1,y,z) then
        self:renderFace(t,x,y,z,Right)
    end
    if self:shouldRenderFace(x,y - 1,z,Bottom) then
        self:renderFace(t,x,y,z,Bottom)
    end
    if self:shouldRenderFace(x,y + 1,z,Top) then
        self:renderFace(t,x,y,z,Top)
    end
    if self:shouldRenderFace(x,y,z - 1) then
        self:renderFace(t,x,y,z,Back)
    end
    if self:shouldRenderFace(x,y,z + 1) then
        self:renderFace(t,x,y,z,Front)
    end
end

function Block:renderInChunk(ts,x,y,z,c)
    local t = self:getTesselator(ts)
    if self:shouldRenderFaceC(c,x - 1,y,z) then
        self:renderFaceC(t,c,x,y,z,Left)
    end
    if self:shouldRenderFaceC(c,x + 1,y,z) then
        self:renderFaceC(t,c,x,y,z,Right)
    end
    if self:shouldRenderFaceC(c,x,y - 1,z,Bottom) then
        self:renderFaceC(t,c,x,y,z,Bottom)
    end
    if self:shouldRenderFaceC(c,x,y + 1,z,Top) then
        self:renderFaceC(t,c,x,y,z,Top)
    end
    if self:shouldRenderFaceC(c,x,y,z - 1) then
        self:renderFaceC(t,c,x,y,z,Back)
    end
    if self:shouldRenderFaceC(c,x,y,z + 1) then
        self:renderFaceC(t,c,x,y,z,Front)
    end
end


function Block:shouldRenderFace(x,y,z)
    return world:isOpacityBlock(x,y,z)
end

function Block:shouldRenderFaceC(c,x,y,z)
    return c:isOpacityBlock(x,y,z)
end

function Block:getBrightness(x,y,z)
    return (1 - GameSetting.Brightness) * world:getBrightness(x,y,z) / Brightness.Max + GameSetting.Brightness
    -- return (1 - GameSetting.Brightness) * 0.9 ^ (Brightness.Max - world:getBrightness(x,y,z)) + GameSetting.Brightness
end

function Block:getBrightnessC(c,x,y,z)
    return (1 - GameSetting.Brightness) * c:getBrightness(x,y,z) / Brightness.Max + GameSetting.Brightness
end

-- 渲染方块的一个面的纹理
function Block:renderFace(t,x,y,z,face)
    local tex = self:getTex(face)
    local u0 = (tex % 16) / 16
    local u1 = u0 + 15.99 / 256
    local v0 = tex // 16 / 16
    local v1 = v0 + 15.99 / 256
    
    local x0 = x
    local x1 = x + 1
    local y0 = y
    local y1 = y + 1
    local z0 = z
    local z1 = z + 1
    
    local c1 = 250
    local c2 = 210
    local c3 = 190
    local c4 = 155
    local b
    local bf = 1 - GameSetting.SmoothLight
    
    local b1,b2
    
    if face == Front then
        b = self:getBrightness(x,y,z + 1) * bf
        b1 = self:getBrightnessAtCoord(x,y,z + 1) + b
        b2 = self:getBrightnessAtCoord(x + 1,y + 1,z + 1) + b
        t:vertexUVC(x0,y0,z1,u0,v0,c2 * b1)
        t:vertexUVC(x1,y0,z1,u1,v0,c2 * (self:getBrightnessAtCoord(x + 1,y,z + 1) + b))
        t:vertexUVC(x1,y1,z1,u1,v1,c2 * b2)
        t:vertexUVC(x1,y1,z1,u1,v1,c2 * b2)
        t:vertexUVC(x0,y1,z1,u0,v1,c2 * (self:getBrightnessAtCoord(x,y + 1,z + 1) + b))
        t:vertexUVC(x0,y0,z1,u0,v0,c2 * b1)
    elseif face == Back then
        b = self:getBrightness(x,y,z - 1) * bf
        b1 = self:getBrightnessAtCoord(x + 1,y,z) + b
        b2 = self:getBrightnessAtCoord(x,y + 1,z) + b
        t:vertexUVC(x1,y0,z0,u0,v0,c2 * b1)
        t:vertexUVC(x0,y0,z0,u1,v0,c2 * (self:getBrightnessAtCoord(x,y,z) + b))
        t:vertexUVC(x0,y1,z0,u1,v1,c2 * b2)
        t:vertexUVC(x0,y1,z0,u1,v1,c2 * b2)
        t:vertexUVC(x1,y1,z0,u0,v1,c2 * (self:getBrightnessAtCoord(x + 1,y + 1,z) + b))
        t:vertexUVC(x1,y0,z0,u0,v0,c2 * b1)
    elseif face == Top then
        b = self:getBrightness(x,y + 1,z) * bf
        b1 = self:getBrightnessAtCoord(x,y + 1,z + 1) + b
        b2 = self:getBrightnessAtCoord(x + 1,y + 1,z) + b
        t:vertexUVC(x0,y1,z1,u0,v0,c1 * b1)
        t:vertexUVC(x1,y1,z1,u1,v0,c1 * (self:getBrightnessAtCoord(x + 1,y + 1,z + 1) + b))
        t:vertexUVC(x1,y1,z0,u1,v1,c1 * b2)
        t:vertexUVC(x1,y1,z0,u1,v1,c1 * b2)
        t:vertexUVC(x0,y1,z0,u0,v1,c1 * (self:getBrightnessAtCoord(x,y + 1,z) + b))
        t:vertexUVC(x0,y1,z1,u0,v0,c1 * b1)
    elseif face == Bottom then
        b = self:getBrightness(x,y - 1,z) * bf
        b1 = self:getBrightnessAtCoord(x,y,z) + b
        b2 = self:getBrightnessAtCoord(x + 1,y,z + 1) + b
        t:vertexUVC(x0,y0,z0,u0,v0,c4 * b1)
        t:vertexUVC(x1,y0,z0,u1,v0,c4 * (self:getBrightnessAtCoord(x + 1,y,z) + b))
        t:vertexUVC(x1,y0,z1,u1,v1,c4 * b2)
        t:vertexUVC(x1,y0,z1,u1,v1,c4 * b2)
        t:vertexUVC(x0,y0,z1,u0,v1,c4 * (self:getBrightnessAtCoord(x,y,z + 1) + b))
        t:vertexUVC(x0,y0,z0,u0,v0,c4 * b1)
    elseif face == Left then
        b = self:getBrightness(x - 1,y,z) * bf
        b1 = self:getBrightnessAtCoord(x,y,z) + b
        b2 = self:getBrightnessAtCoord(x,y + 1,z + 1) + b
        t:vertexUVC(x0,y0,z0,u0,v0,c3 * b1)
        t:vertexUVC(x0,y0,z1,u1,v0,c3 * (self:getBrightnessAtCoord(x,y,z + 1) + b))
        t:vertexUVC(x0,y1,z1,u1,v1,c3 * b2)
        t:vertexUVC(x0,y1,z1,u1,v1,c3 * b2)
        t:vertexUVC(x0,y1,z0,u0,v1,c3 * (self:getBrightnessAtCoord(x,y + 1,z) + b))
        t:vertexUVC(x0,y0,z0,u0,v0,c3 * b1)
    else
        b = self:getBrightness(x + 1,y,z) * bf
        b1 = self:getBrightnessAtCoord(x + 1,y,z + 1) + b
        b2 = self:getBrightnessAtCoord(x + 1,y + 1,z) + b
        t:vertexUVC(x1,y0,z1,u0,v0,c3 * b1)
        t:vertexUVC(x1,y0,z0,u1,v0,c3 * (self:getBrightnessAtCoord(x + 1,y,z) + b))
        t:vertexUVC(x1,y1,z0,u1,v1,c3 * b2)
        t:vertexUVC(x1,y1,z0,u1,v1,c3 * b2)
        t:vertexUVC(x1,y1,z1,u0,v1,c3 * (self:getBrightnessAtCoord(x + 1,y + 1,z + 1) + b))
        t:vertexUVC(x1,y0,z1,u0,v0,c3 * b1)
    end
end

function Block:renderFaceC(t,c,x,y,z,face)
    local tex = self:getTex(face)
    local u0 = (tex % 16) / 16
    local u1 = u0 + 15.99 / 256
    local v0 = tex // 16 / 16
    local v1 = v0 + 15.99 / 256
    
    local xa,za = c.xPos + x,c.zPos + z
    local x0 = xa
    local x1 = xa + 1
    local y0 = y
    local y1 = y + 1
    local z0 = za
    local z1 = za + 1
    
    local c1 = 250
    local c2 = 210
    local c3 = 190
    local c4 = 155
    local b
    local bf = 1 - GameSetting.SmoothLight
    
    local b1,b2
    
    if face == Front then
        b = self:getBrightnessC(c,x,y,z + 1) * bf
        b1 = self:getBrightnessAtCoordC(c,x,y,z + 1) + b
        b2 = self:getBrightnessAtCoordC(c,x + 1,y + 1,z + 1) + b
        t:vertexUVC(x0,y0,z1,u0,v0,c2 * b1)
        t:vertexUVC(x1,y0,z1,u1,v0,c2 * (self:getBrightnessAtCoordC(c,x + 1,y,z + 1) + b))
        t:vertexUVC(x1,y1,z1,u1,v1,c2 * b2)
        t:vertexUVC(x1,y1,z1,u1,v1,c2 * b2)
        t:vertexUVC(x0,y1,z1,u0,v1,c2 * (self:getBrightnessAtCoordC(c,x,y + 1,z + 1) + b))
        t:vertexUVC(x0,y0,z1,u0,v0,c2 * b1)
    elseif face == Back then
        b = self:getBrightnessC(c,x,y,z - 1) * bf
        b1 = self:getBrightnessAtCoordC(c,x + 1,y,z) + b
        b2 = self:getBrightnessAtCoordC(c,x,y + 1,z) + b
        t:vertexUVC(x1,y0,z0,u0,v0,c2 * b1)
        t:vertexUVC(x0,y0,z0,u1,v0,c2 * (self:getBrightnessAtCoordC(c,x,y,z) + b))
        t:vertexUVC(x0,y1,z0,u1,v1,c2 * b2)
        t:vertexUVC(x0,y1,z0,u1,v1,c2 * b2)
        t:vertexUVC(x1,y1,z0,u0,v1,c2 * (self:getBrightnessAtCoordC(c,x + 1,y + 1,z) + b))
        t:vertexUVC(x1,y0,z0,u0,v0,c2 * b1)
    elseif face == Top then
        b = self:getBrightnessC(c,x,y + 1,z) * bf
        b1 = self:getBrightnessAtCoordC(c,x,y + 1,z + 1) + b
        b2 = self:getBrightnessAtCoordC(c,x + 1,y + 1,z) + b
        t:vertexUVC(x0,y1,z1,u0,v0,c1 * b1)
        t:vertexUVC(x1,y1,z1,u1,v0,c1 * (self:getBrightnessAtCoordC(c,x + 1,y + 1,z + 1) + b))
        t:vertexUVC(x1,y1,z0,u1,v1,c1 * b2)
        t:vertexUVC(x1,y1,z0,u1,v1,c1 * b2)
        t:vertexUVC(x0,y1,z0,u0,v1,c1 * (self:getBrightnessAtCoordC(c,x,y + 1,z) + b))
        t:vertexUVC(x0,y1,z1,u0,v0,c1 * b1)
    elseif face == Bottom then
        b = self:getBrightnessC(c,x,y - 1,z) * bf
        b1 = self:getBrightnessAtCoordC(c,x,y,z) + b
        b2 = self:getBrightnessAtCoordC(c,x + 1,y,z + 1) + b
        t:vertexUVC(x0,y0,z0,u0,v0,c4 * b1)
        t:vertexUVC(x1,y0,z0,u1,v0,c4 * (self:getBrightnessAtCoordC(c,x + 1,y,z) + b))
        t:vertexUVC(x1,y0,z1,u1,v1,c4 * b2)
        t:vertexUVC(x1,y0,z1,u1,v1,c4 * b2)
        t:vertexUVC(x0,y0,z1,u0,v1,c4 * (self:getBrightnessAtCoordC(c,x,y,z + 1) + b))
        t:vertexUVC(x0,y0,z0,u0,v0,c4 * b1)
    elseif face == Left then
        b = self:getBrightnessC(c,x - 1,y,z) * bf
        b1 = self:getBrightnessAtCoordC(c,x,y,z) + b
        b2 = self:getBrightnessAtCoordC(c,x,y + 1,z + 1) + b
        t:vertexUVC(x0,y0,z0,u0,v0,c3 * b1)
        t:vertexUVC(x0,y0,z1,u1,v0,c3 * (self:getBrightnessAtCoordC(c,x,y,z + 1) + b))
        t:vertexUVC(x0,y1,z1,u1,v1,c3 * b2)
        t:vertexUVC(x0,y1,z1,u1,v1,c3 * b2)
        t:vertexUVC(x0,y1,z0,u0,v1,c3 * (self:getBrightnessAtCoordC(c,x,y + 1,z) + b))
        t:vertexUVC(x0,y0,z0,u0,v0,c3 * b1)
    else
        b = self:getBrightnessC(c,x + 1,y,z) * bf
        b1 = self:getBrightnessAtCoordC(c,x + 1,y,z + 1) + b
        b2 = self:getBrightnessAtCoordC(c,x + 1,y + 1,z) + b
        t:vertexUVC(x1,y0,z1,u0,v0,c3 * b1)
        t:vertexUVC(x1,y0,z0,u1,v0,c3 * (self:getBrightnessAtCoordC(c,x + 1,y,z) + b))
        t:vertexUVC(x1,y1,z0,u1,v1,c3 * b2)
        t:vertexUVC(x1,y1,z0,u1,v1,c3 * b2)
        t:vertexUVC(x1,y1,z1,u0,v1,c3 * (self:getBrightnessAtCoordC(c,x + 1,y + 1,z + 1) + b))
        t:vertexUVC(x1,y0,z1,u0,v0,c3 * b1)
    end
end

function Block:getTex(face)
    return self.tex
end

function Block.getAABB(x,y,z)
    return AABB(x,y,z,x + 1,y + 1,z + 1)
end

function Block:tick(x,y,z,isMarkedTick)
    
end

-- 相邻方块被更改
function Block:neighborChanged(x,y,z,face,block)
    
end

-- 用指定纹理单独渲染一个方块的一面
function Block.renderTexture(t,x,y,z,face,tex)
    local u0 = (tex % 16) / 16
    local u1 = u0 + 15.99 / 256
    local v0 = tex // 16 / 16
    local v1 = v0 + 15.99 / 256
    
    local x0 = x
    local x1 = x + 1
    local y0 = y
    local y1 = y + 1
    local z0 = z
    local z1 = z + 1
    
    if face == Front then
        t:vertexUV(x0,y0,z1,u0,v0)
        t:vertexUV(x1,y0,z1,u1,v0)
        t:vertexUV(x1,y1,z1,u1,v1)
        t:vertexUV(x1,y1,z1,u1,v1)
        t:vertexUV(x0,y1,z1,u0,v1)
        t:vertexUV(x0,y0,z1,u0,v0)
    elseif face == Back then
        t:vertexUV(x1,y0,z0,u0,v0)
        t:vertexUV(x0,y0,z0,u1,v0)
        t:vertexUV(x0,y1,z0,u1,v1)
        t:vertexUV(x0,y1,z0,u1,v1)
        t:vertexUV(x1,y1,z0,u0,v1)
        t:vertexUV(x1,y0,z0,u0,v0)
    elseif face == Top then
        t:vertexUV(x0,y1,z1,u0,v0)
        t:vertexUV(x1,y1,z1,u1,v0)
        t:vertexUV(x1,y1,z0,u1,v1)
        t:vertexUV(x1,y1,z0,u1,v1)
        t:vertexUV(x0,y1,z0,u0,v1)
        t:vertexUV(x0,y1,z1,u0,v0)
    elseif face == Bottom then
        t:vertexUV(x0,y0,z0,u0,v0)
        t:vertexUV(x1,y0,z0,u1,v0)
        t:vertexUV(x1,y0,z1,u1,v1)
        t:vertexUV(x1,y0,z1,u1,v1)
        t:vertexUV(x0,y0,z1,u0,v1)
        t:vertexUV(x0,y0,z0,u0,v0)
    elseif face == Left then
        t:vertexUV(x0,y0,z0,u0,v0)
        t:vertexUV(x0,y0,z1,u1,v0)
        t:vertexUV(x0,y1,z1,u1,v1)
        t:vertexUV(x0,y1,z1,u1,v1)
        t:vertexUV(x0,y1,z0,u0,v1)
        t:vertexUV(x0,y0,z0,u0,v0)
    else
        t:vertexUV(x1,y0,z1,u0,v0)
        t:vertexUV(x1,y0,z0,u1,v0)
        t:vertexUV(x1,y1,z0,u1,v1)
        t:vertexUV(x1,y1,z0,u1,v1)
        t:vertexUV(x1,y1,z1,u0,v1)
        t:vertexUV(x1,y0,z1,u0,v0)
    end
end

-- 不用纹理渲染
function Block.renderFaceNoTexture(t,x,y,z,face)
    local x0 = x
    local x1 = x + 1
    local y0 = y
    local y1 = y + 1
    local z0 = z
    local z1 = z + 1
    
    if face == Front then
        t:vertex(x0,y0,z1)
        t:vertex(x1,y0,z1)
        t:vertex(x1,y1,z1)
        t:vertex(x1,y1,z1)
        t:vertex(x0,y1,z1)
        t:vertex(x0,y0,z1)
    elseif face == Back then
        t:vertex(x1,y0,z0)
        t:vertex(x0,y0,z0)
        t:vertex(x0,y1,z0)
        t:vertex(x0,y1,z0)
        t:vertex(x1,y1,z0)
        t:vertex(x1,y0,z0)
    elseif face == Top then
        t:vertex(x0,y1,z1)
        t:vertex(x1,y1,z1)
        t:vertex(x1,y1,z0)
        t:vertex(x1,y1,z0)
        t:vertex(x0,y1,z0)
        t:vertex(x0,y1,z1)
    elseif face == Bottom then
        t:vertex(x0,y0,z0)
        t:vertex(x1,y0,z0)
        t:vertex(x1,y0,z1)
        t:vertex(x1,y0,z1)
        t:vertex(x0,y0,z1)
        t:vertex(x0,y0,z0)
    elseif face == Left then
        t:vertex(x0,y0,z0)
        t:vertex(x0,y0,z1)
        t:vertex(x0,y1,z1)
        t:vertex(x0,y1,z1)
        t:vertex(x0,y1,z0)
        t:vertex(x0,y0,z0)
    else
        t:vertex(x1,y0,z1)
        t:vertex(x1,y0,z0)
        t:vertex(x1,y1,z0)
        t:vertex(x1,y1,z0)
        t:vertex(x1,y1,z1)
        t:vertex(x1,y0,z1)
    end
end

-- 获得掉落物品
function Block:getDroppedItem()
    return self
end

-- 方块被放置
function Block:blockBeSet(x,y,z)
    
end

-- 获取方块的layer
function Block:getLayer()
    return 1
end

function Block:getBrightnessAtCoordA(x,y,z)
    return ((self:getBrightness(x - 1,y - 1,z - 1) + self:getBrightness(x,y - 1,z - 1) + self:getBrightness(x - 1,y,z - 1) + self:getBrightness(x - 1,y - 1,z) + self:getBrightness(x,y,z - 1) + self:getBrightness(x,y - 1,z) + self:getBrightness(x - 1,y,z) + self:getBrightness(x,y,z)) / 8) ^ GameSetting.DarkEx * GameSetting.SmoothLight
end
Block.getBrightnessAtCoord = Block.getBrightnessAtCoordA
function Block:getBrightnessAtCoordB(x,y,z)
    return 0
end

function Block:getBrightnessAtCoordCA(c,x,y,z)
    return ((self:getBrightnessC(c,x - 1,y - 1,z - 1) + self:getBrightnessC(c,x,y - 1,z - 1) + self:getBrightnessC(c,x - 1,y,z - 1) + self:getBrightnessC(c,x - 1,y - 1,z) + self:getBrightnessC(c,x,y,z - 1) + self:getBrightnessC(c,x,y - 1,z) + self:getBrightnessC(c,x - 1,y,z) + self:getBrightnessC(c,x,y,z)) / 8) ^ GameSetting.DarkEx * GameSetting.SmoothLight
end
Block.getBrightnessAtCoordC = Block.getBrightnessAtCoordCA
function Block:getBrightnessAtCoordCB(x,y,z)
    return 0
end
